import LXCOM from '../common/common.js'
import linegraph from './linegraph.js'
import { CoordTRFUtil } from '../common/tools/coordtool.js'
import Coord from '../common/struct/coord.js'
import lnActPkg from './action/lineaction.js'

import UtilFuncs from '../common/tools/utilfuncs.js'
var funcs = UtilFuncs.UtilFuncs;

import {LGXEnums}  from '../common/sysenum.js'

import globalConst from '../common/globalConst.js'
var global = globalConst.GlobalConst;

import { GlobalVar } from '../common/globalvar.js'
const ST_featurePT_IDX = 2;//1留给整体移动

class CommLineGraph extends linegraph.LineGraph {
    constructor(type) {
        super(type);
        var p = new Coord.MultiPos();
        this.setPos(p);
        var action = new lnActPkg.LineGraphAction(this);
        this.setActionSvc(action);
        this.m_graphType = LGXEnums.LGXGraphType.CommBusGraph_type;
        this._lineDef.lineWidth = 10;
        this._lineDef.color.setVal(255,0,0);
        this.stColor = new LXCOM.LGXColor();
        this.stColor.setVal(0,255,0,255);

        this.midColor = new LXCOM.LGXColor();
        this.midColor.setVal(255,255,255);

        this.endColor = new LXCOM.LGXColor();
        this.endColor.setVal(255,255,0);

        this._lineDef.color.clone(GlobalVar.visoDefaultFillColor);
    }

    display(map, mapInfo,forClip) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return;
        }
        this.displayGradientBus(map, mapInfo);
        super.displayGraphScope(map, mapInfo);
        this.displayFeaturePoint(map, position.posList, mapInfo);
    }

    displayGradientBus(map, mapInfo) {
        var position = this.getPos();
        var lenth = position.posList.length;
        var prePt = position.posList[0];
        let preSecEnd = { idx: 0, st: { x: 0, y: 0 }, end: { x: 0, y: 0 } };
        let nxtSecEndPt = null;
        for (var i = 1; i < lenth; i++) {
            let pt = position.posList[i];
            if (i + 1 < lenth) {
                nxtSecEndPt = position.posList[i + 1];
            }
            else {
                nxtSecEndPt = null;
            }
            preSecEnd = this.displayGradientBusSec(prePt, pt, map, mapInfo, preSecEnd, nxtSecEndPt);
            if (!preSecEnd) {
                this.displayGradientBusSecOutLine(prePt, pt, map, mapInfo);
            }
            prePt = pt;
        }
    }

    displayGradientBusSec(stPt, endPt, map, mapInfo, preSecEnd, nxtSecEndPt) {
        // console.log("displayGradientBusSec");
        var scaling = mapInfo.getScaling();
        let offsetLen = this._lineDef.lineWidth * 0.5;
        let dis = funcs.distancePoint(stPt, endPt, scaling);
        if (dis < offsetLen * 4) {
            return null;
        }
        var lineSecEdgePtLst = this.getGradientBusSecPtList(stPt, endPt, preSecEnd, nxtSecEndPt);
        if (!lineSecEdgePtLst || (lineSecEdgePtLst && lineSecEdgePtLst.length != 4)) {
            return null;
        }

        //以线段的走向反方向旋转线段与局部坐标轴平行，再进行渐变着色
        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);
        let halfLen = funcs.distancePoint(stPt, endPt, 1) * 0.5;//线段中心世界坐标
        let midPt = { x: 0, y: 0 };
        midPt.x = stPt.x + halfLen * lineVct.m;
        midPt.y = stPt.y + halfLen * lineVct.n;

        let chg2LocalPTList = new Array();
        let angle = lineVct.angleFrmXAxisPositiveDir();
        let rotV = funcs.degree2Radian(angle);
        for (var i = 0; i < 4; i++) {
            let pt = lineSecEdgePtLst[i];
            if (!pt){
                console.log();
            }
            let localpt = funcs.rotate(pt, midPt, -rotV);//反向旋转得局部坐标
            chg2LocalPTList.push(localpt);
        }

        map.beginPath();
        map.lineWidth = 1;
        map.strokeStyle = this._lineDef.color.toHexString();

        var disPos = new Coord.MultiPos();
        var screenMidPt = CoordTRFUtil.world2Screen(midPt, mapInfo);//线段中心绘制坐标
        map.save();
        map.translate(screenMidPt.x, screenMidPt.y);
        map.rotate(-rotV);
        map.translate(-screenMidPt.x, -screenMidPt.y);
        var pt = chg2LocalPTList[0];
        var p = CoordTRFUtil.world2Screen(pt, mapInfo);
        var p0 = p;
        map.moveTo(p.x, p.y);
        disPos.addPoint(p0);
        for (var i = 1; i < 4; i++) {
            pt = chg2LocalPTList[i];
            p = CoordTRFUtil.world2Screen(pt, mapInfo);
            map.lineTo(p.x, p.y);
            disPos.addPoint(p);
        }
        map.lineTo(p0.x, p0.y);
        disPos.addPoint(p0);
        map.stroke();
        map.closePath();

        this.activeFill(disPos, chg2LocalPTList, map, mapInfo);
        map.restore();

        let nextStPt = lineSecEdgePtLst[1];
        let nextEndPt = lineSecEdgePtLst[2];
        if (!preSecEnd) {
            return null;
        }

        let nextSecEnd = { idx: preSecEnd.idx + 1, st: { x: nextStPt.x, y: nextStPt.y }, end: { x: nextEndPt.x, y: nextEndPt.y } };
        return nextSecEnd;
    }

    activeFill = function (disPos, chg2LocalPTList, map, mapInfo) {
        let gradientStPt = disPos.posList[0];
        let gradientEndPt = disPos.posList[3];

        let p1 = chg2LocalPTList[0];
        let p2 = chg2LocalPTList[1];
        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(p1, p2);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        gradientStPt = { x: (p1.x + p2.x) / 2, y: (p1.y + p2.y) / 2 };

        //对侧边框向量
        let p3 = chg2LocalPTList[2];
        let p4 = chg2LocalPTList[3];
        let nextlineVct = new LXCOM.LGXVector();
        nextlineVct.setBy2Pt(p3, p4);

        gradientEndPt = funcs.getTwoLineInterPos(gradientStPt, rotR90Vct, p3, nextlineVct);
        if (!gradientEndPt) {
            return null;
        }

        let stPt = CoordTRFUtil.world2Screen(gradientStPt, mapInfo);
        let endPt = CoordTRFUtil.world2Screen(gradientEndPt, mapInfo);
        let grd = map.createLinearGradient(stPt.x, stPt.y, endPt.x, endPt.y);
        grd.addColorStop(0, this._lineDef.color.toHexString());
        grd.addColorStop(0.5, this.midColor.toHexString());
        grd.addColorStop(1, this._lineDef.color.toHexString());
        map.fillStyle = grd;
        map.fill();
    }



    getGradientBusSecPtList(stPt, endPt, preSecEnd, nxtSecEndPt) {
        if (!preSecEnd) {
            return this.getTwoPtGradientBusSecPtList(stPt, endPt);
        }
        var lineSecEdgePtLst = null;
        if (preSecEnd.idx == 0) {
            if (!nxtSecEndPt) {
                lineSecEdgePtLst = this.getTwoPtGradientBusSecPtList(stPt, endPt);
            }
            else {
                let dis = funcs.distancePoint(nxtSecEndPt, endPt, 1);
                if (dis < global.ZERO_8E) {
                    lineSecEdgePtLst = this.getTwoPtGradientBusSecPtList(stPt, endPt);
                }
                else {
                    lineSecEdgePtLst = this.getGradientFirstBusSecPtList(stPt, endPt, nxtSecEndPt);
                }
            }
        }
        else if (preSecEnd.idx > 0 && !nxtSecEndPt) {
            lineSecEdgePtLst = this.getGradientBusEndSecPtList(stPt, endPt, preSecEnd);
        }
        else {
            let dis = funcs.distancePoint(nxtSecEndPt, endPt, 1);
            if (dis < global.ZERO_8E) {
                lineSecEdgePtLst = this.getTwoPtGradientBusSecPtList(stPt, endPt);
            }
            else {
                lineSecEdgePtLst = this.getGradientBusMidSecPtList(stPt, endPt, preSecEnd, nxtSecEndPt);
            }
        }
        return lineSecEdgePtLst;
    }

    getGradientBusMidSecPtList(stPt, endPt, preSecEnd, nxtSecEndPt) {
        let offsetLen = this._lineDef.lineWidth * 0.5;

        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);

        let rotL90Vct = new LXCOM.LGXVector();
        rotL90Vct.clone(lineVct);
        rotL90Vct.rotate(90);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        //下段线向量
        let nextlineVct = new LXCOM.LGXVector();
        nextlineVct.setBy2Pt(endPt, nxtSecEndPt);

        let nextRotL90Vct = new LXCOM.LGXVector();
        nextRotL90Vct.clone(nextlineVct);
        nextRotL90Vct.rotate(90);

        let nextRotR90Vct = new LXCOM.LGXVector();
        nextRotR90Vct.clone(nextlineVct);
        nextRotR90Vct.rotate(-90);

        //沿线路走向左侧偏移线
        //当前线段起始点沿向量方向逆时针旋转90，取线半宽
        let leftLineStPt = { x: 0, y: 0 };
        leftLineStPt.x = stPt.x + offsetLen * rotL90Vct.m;
        leftLineStPt.y = stPt.y + offsetLen * rotL90Vct.n;

        //当前线段起始点沿向量方向逆时针旋转90，取线半宽
        let leftNextLineStPt = { x: 0, y: 0 };
        leftNextLineStPt.x = endPt.x + offsetLen * nextRotL90Vct.m;
        leftNextLineStPt.y = endPt.y + offsetLen * nextRotL90Vct.n;

        let LeftStLineInterNextPt = funcs.getTwoLineInterPos(leftLineStPt, lineVct, leftNextLineStPt, nextlineVct);
        if (!LeftStLineInterNextPt) {
            return null;
        }

        //沿线路走向右侧偏移线
        //当前线段起始点沿向量方向顺时针旋转90，取线半宽
        let rightLineStPt = { x: 0, y: 0 };
        rightLineStPt.x = stPt.x + offsetLen * rotR90Vct.m;
        rightLineStPt.y = stPt.y + offsetLen * rotR90Vct.n;

        //当前线段起始点沿向量方向顺时针旋转90，取线半宽
        let rightNextLineStPt = { x: 0, y: 0 };
        rightNextLineStPt.x = endPt.x + offsetLen * nextRotR90Vct.m;
        rightNextLineStPt.y = endPt.y + offsetLen * nextRotR90Vct.n;

        let rightStLineInterNextPt = funcs.getTwoLineInterPos(rightLineStPt, lineVct, rightNextLineStPt, nextlineVct);
        if (!rightStLineInterNextPt) {
            return null;
        }
        var lineSecEdgePtLst = new Array();

        let preSecStPt = { x: preSecEnd.st.x, y: preSecEnd.st.y };
        lineSecEdgePtLst.push(preSecStPt);
        lineSecEdgePtLst.push(LeftStLineInterNextPt);
        lineSecEdgePtLst.push(rightStLineInterNextPt);

        let preSecEndPt = { x: preSecEnd.end.x, y: preSecEnd.end.y };
        lineSecEdgePtLst.push(preSecEndPt);
        return lineSecEdgePtLst;
    }

    getGradientFirstBusSecPtList(stPt, endPt, nxtSecEndPt) {
        let offsetLen = this._lineDef.lineWidth * 0.5;

        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);

        let rotL90Vct = new LXCOM.LGXVector();
        rotL90Vct.clone(lineVct);
        rotL90Vct.rotate(90);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        //下段线向量
        let nextlineVct = new LXCOM.LGXVector();
        nextlineVct.setBy2Pt(endPt, nxtSecEndPt);

        let nextRotL90Vct = new LXCOM.LGXVector();
        nextRotL90Vct.clone(nextlineVct);
        nextRotL90Vct.rotate(90);

        let nextRotR90Vct = new LXCOM.LGXVector();
        nextRotR90Vct.clone(nextlineVct);
        nextRotR90Vct.rotate(-90);

        //沿线路走向左侧偏移线
        //当前线段起始点沿向量方向逆时针旋转90，取线半宽
        let leftLineStPt = { x: 0, y: 0 };
        leftLineStPt.x = stPt.x + offsetLen * rotL90Vct.m;
        leftLineStPt.y = stPt.y + offsetLen * rotL90Vct.n;

        //当前线段起始点沿向量方向逆时针旋转90，取线半宽
        let leftNextLineStPt = { x: 0, y: 0 };
        leftNextLineStPt.x = endPt.x + offsetLen * nextRotL90Vct.m;
        leftNextLineStPt.y = endPt.y + offsetLen * nextRotL90Vct.n;

        let LeftStLineInterNextPt = funcs.getTwoLineInterPos(leftLineStPt, lineVct, leftNextLineStPt, nextlineVct);

        //沿线路走向右侧偏移线
        //当前线段起始点沿向量方向顺时针旋转90，取线半宽
        let rightLineStPt = { x: 0, y: 0 };
        rightLineStPt.x = stPt.x + offsetLen * rotR90Vct.m;
        rightLineStPt.y = stPt.y + offsetLen * rotR90Vct.n;

        //当前线段起始点沿向量方向顺时针旋转90，取线半宽
        let rightNextLineStPt = { x: 0, y: 0 };
        rightNextLineStPt.x = endPt.x + offsetLen * nextRotR90Vct.m;
        rightNextLineStPt.y = endPt.y + offsetLen * nextRotR90Vct.n;

        let rightStLineInterNextPt = funcs.getTwoLineInterPos(rightLineStPt, lineVct, rightNextLineStPt, nextlineVct);
        var lineSecEdgePtLst = new Array();

        lineSecEdgePtLst.push(leftLineStPt);
        lineSecEdgePtLst.push(LeftStLineInterNextPt);
        lineSecEdgePtLst.push(rightStLineInterNextPt);
        lineSecEdgePtLst.push(rightLineStPt);
        return lineSecEdgePtLst;
    }

    getGradientBusEndSecPtList(stPt, endPt, preSecEnd) {
        let offsetLen = this._lineDef.lineWidth * 0.5;

        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);

        let rotL90Vct = new LXCOM.LGXVector();
        rotL90Vct.clone(lineVct);
        rotL90Vct.rotate(90);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        var lineSecEdgePtLst = new Array();
        let p1 = { x: preSecEnd.st.x, y: preSecEnd.st.y };
        lineSecEdgePtLst.push(p1);

        //终点沿向量方向逆时针旋转90，取线半宽
        let p2 = { x: 0, y: 0 };
        p2.x = endPt.x + offsetLen * rotL90Vct.m;
        p2.y = endPt.y + offsetLen * rotL90Vct.n;
        lineSecEdgePtLst.push(p2);

        //终点沿向量方向顺时针旋转90，取线半宽
        let p3 = { x: 0, y: 0 };
        p3.x = endPt.x + offsetLen * rotR90Vct.m;
        p3.y = endPt.y + offsetLen * rotR90Vct.n;
        lineSecEdgePtLst.push(p3);

        let p4 = { x: preSecEnd.end.x, y: preSecEnd.end.y };
        lineSecEdgePtLst.push(p4);

        return lineSecEdgePtLst;
    }
    getTwoPtGradientBusSecPtList(stPt, endPt) {
        let offsetLen = this._lineDef.lineWidth * 0.5;

        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);

        let rotL90Vct = new LXCOM.LGXVector();
        rotL90Vct.clone(lineVct);
        rotL90Vct.rotate(90);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        var lineSecEdgePtLst = new Array();
        //起始点沿向量方向逆时针旋转90，取线半宽
        let p1 = { x: 0, y: 0 };
        p1.x = stPt.x + offsetLen * rotL90Vct.m;
        p1.y = stPt.y + offsetLen * rotL90Vct.n;
        
        //起始点沿向量方向顺时针旋转90，取线半宽
        let p2 = { x: 0, y: 0 };
        p2.x = stPt.x + offsetLen * rotR90Vct.m;
        p2.y = stPt.y + offsetLen * rotR90Vct.n;

        //终点沿向量方向顺时针旋转90，取线半宽
        let p3 = { x: 0, y: 0 };
        p3.x = endPt.x + offsetLen * rotR90Vct.m;
        p3.y = endPt.y + offsetLen * rotR90Vct.n;

        //终点沿向量方向顺时针旋转90，取线半宽
        let p4 = { x: 0, y: 0 };
        p4.x = endPt.x + offsetLen * rotL90Vct.m;
        p4.y = endPt.y + offsetLen * rotL90Vct.n;

        //下面顺序不能乱，渐变要依据这个顺序来去起点和终点坐标
        lineSecEdgePtLst.push(p1);
        lineSecEdgePtLst.push(p4);
        lineSecEdgePtLst.push(p3);
        lineSecEdgePtLst.push(p2);
        return lineSecEdgePtLst;
    }

    displayGradientBusSecOutLine(stPt, endPt, map, mapInfo) {
        var scaling = mapInfo.getScaling();
        let offsetLen = this._lineDef.lineWidth * 0.5;
        let dis = funcs.distancePoint(stPt, endPt, scaling);
        if (dis < offsetLen * 4) {
            return;
        }

        let lineVct = new LXCOM.LGXVector();
        lineVct.setBy2Pt(stPt, endPt);

        let rotL90Vct = new LXCOM.LGXVector();
        rotL90Vct.clone(lineVct);
        rotL90Vct.rotate(90);

        let rotR90Vct = new LXCOM.LGXVector();
        rotR90Vct.clone(lineVct);
        rotR90Vct.rotate(-90);

        var lineSecEdgePtLst = new Array();
        //起始点沿向量方向逆时针旋转90，取线半宽
        let p1 = { x: 0, y: 0 };
        p1.x = stPt.x + offsetLen * rotL90Vct.m;
        p1.y = stPt.y + offsetLen * rotL90Vct.n;
        lineSecEdgePtLst.push(p1);

        //起始点沿向量方向顺时针旋转90，取线半宽
        let p2 = { x: 0, y: 0 };
        p2.x = stPt.x + offsetLen * rotR90Vct.m;
        p2.y = stPt.y + offsetLen * rotR90Vct.n;
        lineSecEdgePtLst.push(p2);

        //终点沿向量方向顺时针旋转90，取线半宽
        let p3 = { x: 0, y: 0 };
        p3.x = endPt.x + offsetLen * rotR90Vct.m;
        p3.y = endPt.y + offsetLen * rotR90Vct.n;
        lineSecEdgePtLst.push(p3);

        //终点沿向量方向顺时针旋转90，取线半宽
        let p4 = { x: 0, y: 0 };
        p4.x = endPt.x + offsetLen * rotL90Vct.m;
        p4.y = endPt.y + offsetLen * rotL90Vct.n;
        lineSecEdgePtLst.push(p4);

        var disPos = new Coord.MultiPos();
        map.beginPath();
        map.lineWidth = 1;
        map.strokeStyle = this._lineDef.color.toHexString();

        var pt = lineSecEdgePtLst[0];
        var p = CoordTRFUtil.world2Screen(pt, mapInfo);
        var p0 = p;
        disPos.posList.push(p0);
        map.moveTo(p.x, p.y);
        for (var i = 1; i < 4; i++) {
            pt = lineSecEdgePtLst[i];
            p = CoordTRFUtil.world2Screen(pt, mapInfo);
            map.lineTo(p.x, p.y);
            disPos.posList.push(p);
        }
        map.lineTo(p0.x, p0.y);
        disPos.posList.push(p0);
        map.stroke();
        map.closePath();
    }

    disInSymbol(transformInfo,map, mapInfo,forClip) {

    }

    calScope(mapscale) {
        var position = this.getPos();
        if (position.posList.length < 2) {
            return;
        }
        var rect = position.getZone();
        rect.expand(this._lineDef.lineWidth);
        this._zone.clone(rect);
    }

    distance(tPos, scaling, mapscale) {
        var position = this.getPos();
        var lenth = position.posList.length;
        if (lenth < 2) {
            return -1;
        }
        if (!super.preCheckInScope(tPos, scaling)) {
            return -1;
        }

        var cmpGap = super.getSelCmpGap(scaling, mapscale);
        var dis = -1;
        var pCntPos = null;
        var pPrePos = position.posList[0];
        for (var i = 0; i < lenth - 1; i++) {
            pCntPos = position.posList[i + 1];
            var lLen = funcs.distanceLineSec4Visual(tPos, pPrePos, pCntPos, scaling);
            if ((lLen < dis) || (dis < 0)) {
                dis = lLen;
            }
            if (dis <= cmpGap) {
                return 0;
            }
            pPrePos = pCntPos;
        }
        if (dis > cmpGap) {
            dis = -1;
        }
        return dis;
    }

    displayFeaturePoint(map,ptLst,mapInfo) {
        if (!this._selected) {
            return;
        }
        var lenth = ptLst.length;
        for (var i = 0; i < lenth; i++) {
            var pt = ptLst[i];
            let screenpt = CoordTRFUtil.world2Screen(pt, mapInfo);
            var x = screenpt.x;
            var y = screenpt.y;
            super.drawFocusPoint(map, x, y, "#0000ff");
        }
    }

    calculateSelKind(tPoint, scaling, mapscale) {
        let seleKind = super.calculateSelKind(tPoint, scaling, mapscale);
        return seleKind;
    }

    movePosOffset(tOffset, modCmdInfo) {
        if (this._selKind < 1) {
            return;
        }

        let seleKind = this.getSelKind();
        let position = this.getPos();
        let lenth = position.posList.length;
        if (seleKind == 1) {
            //整体移动
            this.translate(tOffset, modCmdInfo.mapscale, false);
        }
        else if (seleKind < (lenth + ST_featurePT_IDX) && seleKind >= ST_featurePT_IDX) {
            //移动顶点
            let selPosIdx = seleKind - ST_featurePT_IDX;
            this.translateSelVertext(selPosIdx, position, tOffset);
        }
        let copyPosition = this.getPosCopy();
        let prePtCount = copyPosition.posList.length;
        let finalList = funcs.removeCollapsePoint(copyPosition.posList);
        if (prePtCount != finalList.length){
            this.setSelKind(0);
        }
        copyPosition.clear();
        finalList.forEach(pt => {
            copyPosition.addPoint(pt);
        });
        this.setPos(copyPosition);
        this.calScope(1);

    }

    getMainFeaturePTLst(tFeaturePTLst) {
        var position = this.getPos();
        var lenth = position.posList.length;
        for (var i = 0; i < lenth; i++) {
            var pt = position.posList[i];
            tFeaturePTLst.push({pt,kind:LGXEnums.AuxPointKind.end});
        }
    }

    assignInfo(info) {
        super.assignInfo(info);
    }

    modifyAttribute(obj, mapscale) {
        super.modifyCommonAttribute(obj);
        this.calScope(mapscale);
    }

    toInfo() {
        return super.toInfo();
    }

    //复制粘贴时，从复制源对象复制属性到本图形对应属性----虚函数，由实体继承类实现
    copySubPropFromBuf(bufInfo,tx,ty){
        this.copyCommnonPropFromBuf(bufInfo,tx,ty);
    }

}


export default { CommLineGraph }
